#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os
import shutil
import sys

execfile(os.path.join(sys.path[0], "framework.py"))

from oriolus.pith.archivers.zip import ZipArchiver, ZipError
from unittest import TestCase, TestLoader, TextTestRunner

class TestArchiver(TestCase):
    def setUp(self):
        self.__testdata_dir_base = os.path.join(".", "testdata")
        self.__testdata_output = os.path.join(self.__testdata_dir_base, "output")
        self.__testdata_dir = os.path.join(self.__testdata_dir_base, "testdata_to_compress")
        self.__compressed_dir = os.path.join(".", "comressed")
        self.__decompressed_dir = os.path.join(".", "decomressed")
        self.__temp_dirs = (self.__testdata_dir, self.__testdata_output, self.__compressed_dir, self.__decompressed_dir)
        map(self.__create_dir, self.__temp_dirs)

    def tearDown(self):
        map(self.__remove_dir, self.__temp_dirs)

    def test_zip1(self):
        test_data = (("", "in.file", "abcdабвг1234"), )
        self.__create_test_files(test_data)
        archive_path = os.path.join(self.__compressed_dir, "out.file")

        archiver = ZipArchiver()
        archiver.archive(self.__testdata_dir, archive_path)
        archiver.extract(archive_path, self.__decompressed_dir)

        self.__assert_that_decommpression_works()

    def test_zip2(self):
        test_data = (("dir1", "file1.txt", "abcdабвг1234lkjef0u34 34\n\r  24"),
            (os.path.join("dir1", "dir2"), "file2.txt", "abcdабвг1234i3240   lkjscv 9823 "),
            (os.path.join("dir1", "dir2"), "file3.txt", "abcdабвг1234la 223-23=-*&^#*&!#$"))
        self.__create_test_files(test_data)
        archive_path = os.path.join(self.__compressed_dir, "archive.zip")

        archiver = ZipArchiver()
        archiver.archive(self.__testdata_dir, archive_path)
        archiver.extract(archive_path, self.__decompressed_dir)

        self.__assert_that_decommpression_works()

    def test_zip3(self):
        test_data = (("dir1", "file1.txt", "abcdабвг1234lkjef0u34 34\n\r  24"),
            (os.path.join("dir1", "dir2"), "file2.txt", "abcdабвг1234i3240   lkjscv 9823 "),
            (os.path.join("dir1", "dir3"), None, None),
            ("dir4", None, None))
        self.__create_test_files(test_data)
        archive_path = os.path.join(self.__compressed_dir, "archive.zip")

        archiver = ZipArchiver()
        archiver.archive(self.__testdata_dir, archive_path)
        archiver.extract(archive_path, self.__decompressed_dir)

        self.__assert_that_decommpression_works()
        
    def test_zip4(self):
        test_data = (("", "file1.txt", "abcdабвг1234lkjef0u34 34\n\r  24"),
            ("dir1", None, None))
        self.__create_test_files(test_data)
        archive_path = os.path.join(self.__compressed_dir, "archive.zip")

        archiver = ZipArchiver()
        archiver.archive(self.__testdata_dir, archive_path)
        archiver.extract(archive_path, self.__decompressed_dir)

        self.__assert_that_decommpression_works()
        
#    def test_file_packet_with_relative_path2(self):
#        dir = r"C:\tmp_dir"
#        packet_path = r"C:\ProgramData\cache"
#        #names = ["DBus-net35-1.0.0.0"]
#        names = os.listdir(packet_path)
#        archiver = ZipArchiver()
#        for i in range(1, 2):
#            for name in names:
#                print name
#                archiver.extract(os.path.join(packet_path, name), dir)
#                if not os.path.isdir(os.path.join(dir, "data")):
#                    print "Warning"
#                os.remove(os.path.join(dir, "META"))
#                os.remove(os.path.join(dir, "CHECKSUMS"))
#                shutil.rmtree(os.path.join(dir, "scripts"))
#                #shutil.rmtree(os.path.join(dir, "data"))
#                self.__rmtree(os.path.join(dir, "data"))

    def __rmtree(self, path):
        for file in os.listdir(path):
            file_path = os.path.join(path,  file)
            if os.path.isdir(file_path):
                self.__rmtree(file_path)
            else:
                os.remove(file_path)
        os.rmdir(path)

    def test_compressed_archive(self):
        archiver = ZipArchiver()
        path_to_arch = os.path.join(self.__testdata_dir_base, "compressed_packets")
        archive_path = os.path.join(path_to_arch, "packet.zip")

        archiver.extract(archive_path, self.__testdata_output)
        test_files = self.__create_file_list(self.__testdata_output, "META", "scripts/preinstall")
        
        map(self.__assert_test_archive, test_files)
        
    def test_missing_archive(self):
        archiver = ZipArchiver()
        path_to_arch = os.path.join(self.__testdata_dir_base, "packets")
        archive_path = os.path.join(path_to_arch, "missing_packet.zip")
        
        self.assertRaises(ZipError, archiver.extract, archive_path, self.__testdata_output)

    def test_decompress_precreated_packet(self):
        archiver = ZipArchiver()
        path_to_arch = os.path.join(self.__testdata_dir_base, "compressed_packets")
        archive_path = os.path.join(path_to_arch, "packet_2.zip")

        archiver.extract(archive_path, self.__testdata_output)
        test_files = self.__create_file_list(self.__testdata_output, "META", "TEST_DATA", "data/resource.txt", 
            "data/dir1", "scripts/preinstall", "scripts/postinstall", "scripts/preremove","scripts/postremove")
        map(self.__assert_test_archive, test_files)

    def __assert_test_archive(self, path):
        self.assertTrue(os.path.exists(path))

    def __create_file_list(self, base_path, *files):
        result = []
        for each in files:
            result.append(os.path.join(base_path, each))

        return result

    def __assert_that_decommpression_works(self):
        for root, dirs, files in os.walk(self.__testdata_dir):
            for test_data_dir in dirs:
                testdata_dir_path = os.path.join(root, test_data_dir)
                same_decompressed_dir_path = testdata_dir_path.replace(self.__testdata_dir, self.__decompressed_dir)

                self.assertTrue(os.path.exists(same_decompressed_dir_path),
                    "Directory '%s' doesn't exist." % same_decompressed_dir_path)
            for test_data_file in files:
                testdata_file_path = os.path.join(root, test_data_file)
                same_decompressed_file_path = testdata_file_path.replace(self.__testdata_dir, self.__decompressed_dir)
                self.assertTrue(os.path.exists(same_decompressed_file_path),
                    "File '%s' doesn't exist." % same_decompressed_file_path)

                expected_data = file(testdata_file_path).read()
                actual_data = file(same_decompressed_file_path).read()

                self.assertEquals(expected_data, actual_data,
                    "Data in file '%s' is not equal to data from file '%s'." % (same_decompressed_file_path, testdata_file_path))

    def __create_test_files(self, test_data):
        for path, filename, data in test_data:
            self.__create_test_file(os.path.join(self.__testdata_dir, path), filename, data)

    def __create_test_file(self, path, filename, data):
        self.__create_dir(path)

        if filename: 
            file = open(os.path.join(path, filename), "w")
    
            try:
                file.write(data)
            finally:
                file.close()

    def __create_dir(self, path):
        if os.path.exists(path):
            self.__remove_dir(path)

        os.makedirs(path)

    def __remove_dir(self, path):
        if os.path.isdir(path):
            shutil.rmtree(path)

if __name__ == "__main__":
    suite = TestLoader().loadTestsFromTestCase(TestArchiver)
    TextTestRunner(verbosity=2).run(suite)